package com.sunwayhorizo.health.business.registries.threelevels;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;

import org.jboss.seam.Component;
import org.jboss.seam.annotations.Name;

import com.sunwayhorizo.health.business.base.BaseManager;
import com.sunwayhorizo.health.business.dto.ResultsDTO;
import com.sunwayhorizo.health.business.dto.patad.empi.PatientBaseInfoDTO;
import com.sunwayhorizo.health.business.dto.registries.MedicalTeamDTO;
import com.sunwayhorizo.health.business.dto.registries.ThreeLevelsPhysicianDTO;
import com.sunwayhorizo.health.business.patad.encounter.ReceivingManagerLocal;
import com.sunwayhorizo.health.business.patad.encounter.query.PatientEncounterQueryLocal;
import com.sunwayhorizo.health.business.registries.employee.EmployeeManagerLocal;
import com.sunwayhorizo.health.business.registries.organization.query.DepartmentQueryLocal;
import com.sunwayhorizo.health.business.registries.threelevels.query.ThreeLevelQueryLocal;
import com.sunwayhorizo.health.common.DataTypeUtil;
import com.sunwayhorizo.health.common.ListUtil;
import com.sunwayhorizo.health.common.StrUtil;
import com.sunwayhorizo.health.hl7.common.Hl7Exception;
import com.sunwayhorizo.health.hl7.datatypes.BAG_EN;
import com.sunwayhorizo.health.hl7.datatypes.ED;
import com.sunwayhorizo.health.hl7.datatypes.II;
import com.sunwayhorizo.health.hl7.persistent.RimCoreEntyNameUses;
import com.sunwayhorizo.health.hl7.persistent.RimCoreEntyNames;
import com.sunwayhorizo.health.hl7.rim.Act;
import com.sunwayhorizo.health.hl7.rim.ActParticipation;
import com.sunwayhorizo.health.hl7.rim.ControlAct;
import com.sunwayhorizo.health.hl7.rim.Employee;
import com.sunwayhorizo.health.hl7.rim.Organization;
import com.sunwayhorizo.health.hl7.rim.PatientEncounter;
import com.sunwayhorizo.health.hl7.rim.Role;
import com.sunwayhorizo.health.hl7.vocabulary.ActCode;
import com.sunwayhorizo.health.hl7.vocabulary.ActMood;
import com.sunwayhorizo.health.hl7.vocabulary.EntityCode;
import com.sunwayhorizo.health.hl7.vocabulary.EntityDeterminer;
import com.sunwayhorizo.health.hl7.vocabulary.EntityIICode;
import com.sunwayhorizo.health.hl7.vocabulary.EntityNameUse;
import com.sunwayhorizo.health.hl7.vocabulary.ParticipationType;
import com.sunwayhorizo.health.hl7.vocabulary.RoleClass;
import com.sunwayhorizo.health.hl7.vocabulary.RoleCode;

/**
 * @ClassName ThreeLevelsPhysicianManager <br>
 * @PackageName com.sunwayhorizo.health.business.registries.threelevels <br>
 * @Description 三级医师管理 <br>
 * @Author jinzw <br>
 * @Date 2011-5-12 <br>
 * @Version 1.0 <br>
 * @ModifiedDesc <br>
 * @ModifiedDate <br>
 * @ModifiedBy <br>
 * @Email jinzw@sunwaysoft.com.cn <br>
 * @Copyright 2010-2020 horizo All Rights Reserved. <br>
 */

@Stateless
@Name("ThreeLevelsPhysicianManager")
public class ThreeLevelsPhysicianManager extends BaseManager implements ThreeLevelsPhysicianManagerLocal
{

    private DepartmentQueryLocal departmentQuery = (DepartmentQueryLocal) Component.getInstance("DepartmentQuery");
    private ThreeLevelQueryLocal threeLevelQuery = (ThreeLevelQueryLocal) Component.getInstance("ThreeLevelQuery");
    private PatientEncounterQueryLocal patientEncounterManager = (PatientEncounterQueryLocal) Component.getInstance("PatientEncounterQuery");

    @SuppressWarnings("null")
    public ResultsDTO newThreeLevelsPhysician(MedicalTeamDTO dto) throws Hl7Exception
    {

        if (dto == null && StrUtil.isEmpty(dto.getMedicalTeamName()) && StrUtil.isNotEmpty(dto.getMedicalCode()))
        {
            return getResultsDTO("医疗组名称为空，不能新增", false, null);
        }
       
        // 创建ACT
        Act registrationAct = getActFactory().newRegistryAct(ActMood.EVN, ActCode.MEDICALTEAM, null);
        
        //创建角色        
        Role role = converMedicalTeamRole(dto);
        
        //角色参与到动作关系列表中
        ActParticipation patPart = getActFactory().newActParticipation();
        patPart.setTypeCode(ParticipationType.SBJ);
        addParticipation(role, patPart);
        
        // 判断三级医生是否为空，如果不为空，设置该工作组下的所有三级医生
        if (ListUtil.isNotEmpty(dto.getListThreeLevel()))
        {
            setThreeLevelByAct(null,dto.getListThreeLevel());
        }
           
        // 创建controlAct关系
        ControlAct controlAct = newControlAct(registrationAct);
        //持久化
        save(controlAct);
        
        log.info("新增医疗组-三级医生成功。医疗组id="+role.getRoleId().toString());
        return getResultsDTO("新增三级医师成功", true, role.getRoleId().toString());

    }


    @SuppressWarnings({ "rawtypes" })
    public ResultsDTO delThreeLevelsPhysician(List list) throws Hl7Exception
    {
        for (int i = 0; i < list.size(); i++)
        {
            String id = (String) list.get(i);
            ActParticipation ap = threeLevelQuery.findActPrtcptnsByRoleId(Long.valueOf(id), ParticipationType.DIR.code().toString());
            if (ap != null && ap.getTypecode().equals(ParticipationType.DIR))
             {
                  em.remove(ap);
                  em.flush();
                  log.info("删除三级医生关系成功");
             }
        }
        return getResultsDTO("删除三级医生成功", true, null);
    }


    @SuppressWarnings({ "rawtypes", "unused" })
    public ResultsDTO delMedicalTeam(List list) throws Hl7Exception
    {
        if (ListUtil.isEmpty(list))
            return this.getResultsDTO("医疗组编号为空，不能删除", true, null);
        for (int i = 0; i < list.size(); i++)
        {
            String medicalId = (String) list.get(i);
            Role role = baseQuery.findRoleById(Long.parseLong(medicalId));
            // 判断该医疗组下面是否有三级医生关系，如果有，不能删除
            List<ActParticipation> listPrtcptns = threeLevelQuery.findActPrtcptnsByAct((role != null ? role.getRoleId() : 0L),ParticipationType.SBJ.code().toString());

            if (ListUtil.isNotEmpty(listPrtcptns))
            {
                for (ActParticipation prtcptns : listPrtcptns)
                {
                    if (prtcptns.getTypecode().equals(ParticipationType.DIR))
                    {
                        log.info("该医疗组下面有三级医生关系，不能删除该医疗组");
                        return this.getResultsDTO("该医疗组下面有三级医生关系，不能删除该医疗组", true, null);
                    }
                }
            }
            em.remove(role.getPlayerEntity());
            em.remove(role);
            log.info("删除医疗组成功");
            return this.getResultsDTO("删除医疗组成功", true, null);
        }
        return this.getResultsDTO("删除医疗组成功", true, null);
    }


    public ResultsDTO updateThreeLevelsPhysician(MedicalTeamDTO dto) throws Hl7Exception
    {

        // 查询医疗组
        Role role = baseQuery.findRoleById(Long.parseLong(dto.getMedicalTeamId()));
        // 修改医疗组基本信息
        modfiyThreeLevelsBaseInfo(role, dto);
        // 修改三级医生关系
        modfiyThreeLevelsPhysician(role, dto.getListThreeLevel());
        return this.getResultsDTO("三级医生修改成功", true, null);
    }


    public ResultsDTO findThreeLevelsPhysicianList(String workgroupId) throws Hl7Exception
    {
        if (StrUtil.isEmpty(workgroupId))
            return getResultsDTO("工作组为空，没有找到对应的结果", true, null);
        List<Role> list = threeLevelQuery.findThreeLevelListByWorkGroupId(workgroupId);
        List<MedicalTeamDTO> returnList = new ArrayList<MedicalTeamDTO>();
        for (Role role : list)
        {
            MedicalTeamDTO dto = convertDtoToRole(role);
            returnList.add(dto);
        }
        return getResultsDTO("查询到三级医师数据", true, returnList);
    }


    public ResultsDTO validateThreeLevelsCode(String code) throws Hl7Exception
    {
        boolean flag = baseQuery.findRimCoreEntyIiByCode(code);
        if (flag)
        {
            return this.getResultsDTO("编码不存在", true, "1");
        }
        else
            return this.getResultsDTO("编码存在", true, "0");
    }


    public ThreeLevelsPhysicianDTO findThreeLevelsDTOByDoctId(String doctId) throws Hl7Exception
    {
        List<ActParticipation> list = threeLevelQuery.findActPrtcptnsByRole(Long.valueOf(doctId), ParticipationType.DIR.code().toString());
        if (ListUtil.isNotEmpty(list))
        {
            for (ActParticipation prtcptns : list)
            {
                if (prtcptns.getTypecode().equals(ParticipationType.DIR))
                {
                    ThreeLevelsPhysicianDTO threeLever = converThreeLevelsPhysicianDTO(prtcptns);
                    return threeLever;
                }
            }
        }
        return null;
    }

    @Deprecated
    public ThreeLevelsPhysicianDTO findThreeLevelsDTOByPatienId(String patientId) throws Hl7Exception
    {
        PatientEncounter patientEncounter = patientEncounterManager.findRecieveingEncounterByPatientRoleId(patientId);
        List<ActParticipation> partList = patientEncounter.getParticipations();
        if (ListUtil.isNotEmpty(partList))
        {
            for (ActParticipation part : partList)
            {
                if (part.getTypeCode().equals(ParticipationType.DIR))
                {
                    ThreeLevelsPhysicianDTO threeLevel = converThreeLevelsPhysicianDTO(part);
                    return threeLevel;
                }
            }
        }
        return null;
    }

    @Deprecated
    public ResultsDTO modfiyThreeLevelByPatient(ThreeLevelsPhysicianDTO threeLevel) throws Hl7Exception
    {
        if (StrUtil.isEmpty(threeLevel.getPatientId()))
            return this.getResultsDTO("患者信息为空，不能修改三级医生关系", true, null);
        // 根据患者id拿到患者接诊动作

        PatientEncounter patientEncounter = patientEncounterManager.findRecieveingEncounterByPatientRoleId(threeLevel.getPatientId());
        // 从act里面拿到partList
        List<ActParticipation> prctList = patientEncounter.getParticipations();
        long flag = 0;
        if (ListUtil.isNotEmpty(prctList))
        {
            for (ActParticipation partcptns : prctList)
            {
                if (partcptns.getTypeCode().equals(ParticipationType.DIR))
                {
                    if (!threeLevel.getDoctorId().equals(String.valueOf(partcptns.getRoleparticipation().getRoleId())))
                    {
                        Role role = baseQuery.findRoleById(Long.valueOf(threeLevel.getDoctorId()));
                        if (null != role)
                            partcptns.setRoleparticipation(role);
                        log.info("ThreeLevelsPhysicianManager-modfiyThreeLevelsPhysician:经治医生修改");
                        // 修改患者的经治医生
                        ReceivingManagerLocal receivingManager = (ReceivingManagerLocal) Component.getInstance("ReceivingManager");
                        receivingManager.updateDoctorByPatientId(threeLevel.getEncounteId(), (Employee) role);
                    }
                    partcptns.setSignatureCode(DataTypeUtil.getCE(threeLevel.getAttendingPhysicianId()));
                    partcptns.setFunctionCode(DataTypeUtil.getCE(threeLevel.getChiefDoctorId()));
                    em.merge(partcptns);
                    flag = 1;
                }
            }
            // 如果患者在接诊过程中没有绑定三级医生，在三级医生修改中重新加三级医生
            if (flag == 0)
            {
                List<ThreeLevelsPhysicianDTO> list = new ArrayList<ThreeLevelsPhysicianDTO>();
                list.add(threeLevel);
                setThreeLevelByAct(patientEncounter, list);
            }
        }
        return this.getResultsDTO("修改患者三级医生成功", true, null);
    }

   // 设置医疗组下面的三级医生,添加修改都用此方法
    private void setThreeLevelByAct(Act act, List<ThreeLevelsPhysicianDTO> list) throws Hl7Exception
    {
        Employee doctor = null;
        // 判断是否有三级医生信息
        if (ListUtil.isNotEmpty(list))
        {
            for (ThreeLevelsPhysicianDTO threeLevelsDto : list)
            {
                if (StrUtil.isNotEmpty(threeLevelsDto.getDoctorId()) && StrUtil.isNotEmpty(threeLevelsDto.getAttendingPhysicianId())
                        && StrUtil.isNotEmpty(threeLevelsDto.getChiefDoctorId()))
                {
                    // 医师，主治医师，主任医师角色
                    EmployeeManagerLocal empLocal = (EmployeeManagerLocal) Component.getInstance("EmployeeManager");
                    doctor = empLocal.findEmployeeDetail(Long.parseLong(threeLevelsDto.getDoctorId()), null);
                    ActParticipation participation = getActFactory().newActParticipation();
                    // 上级医生id
                    participation.setSignatureCode(DataTypeUtil.getCE(threeLevelsDto.getAttendingPhysicianId()));
                    // 主任医生id
                    participation.setFunctionCode(DataTypeUtil.getCE(threeLevelsDto.getChiefDoctorId()));
                    participation.setTypeCode(ParticipationType.DIR);
                    if(act == null)
                    {
                        addParticipation(doctor,participation);
                    }
                    else
                    {
                        act.addParticipation(participation, doctor);
                    }
                   

                }
            }
        }
    }


    private void converOrganizationTo(Organization organization, MedicalTeamDTO dto) throws Hl7Exception
    {
            // 处理医疗组名称
            String orgenType[] = { null };
            if (StrUtil.isNotEmpty(dto.getMedicalTeamName()))
            {
                String medicalName = dto.getMedicalTeamName();
                String[] orgenName = { medicalName };
                String medicalNameUseCode = EntityNameUse.L.code().toString();
                BAG_EN bagEnName = DataTypeUtil.getBagEN(orgenName, orgenType, medicalNameUseCode);
                organization.setName(bagEnName);
            }

          // 描述
            ED desc = DataTypeUtil.getED(dto.getMedicalDesc());
            organization.setDesc(desc);

        // 医疗组编码
        if (null != organization)
        {
            II id = DataTypeUtil.getII(root, dto.getMedicalCode(), "true", EntityIICode.MEDICALTEAMCODE.toString());
            organization.setId(id);
        }

    }


    private void modfiyThreeLevelsBaseInfo(Role role, MedicalTeamDTO dto) throws Hl7Exception
    {
        Organization organization = (Organization) role.getPlayerEntities();
        converOrganizationTo(organization, dto);
        role.setPlayerEntity(organization);
    }


    //修改三级医生关系
    private void modfiyThreeLevelsPhysician(Role role, List<ThreeLevelsPhysicianDTO> threeLevelList) throws Hl7Exception
    {
        List<ActParticipation> prtcpList = threeLevelQuery.findActPrtcptnsByAct(role.getRoleId(), ParticipationType.SBJ.code().toString());
        Act act = null;
        // 需要新增的三级医生关系集合
        List<ThreeLevelsPhysicianDTO> newThreeLevelList = threeLevelList;
        List<ActParticipation> delThreeLevelList = new ArrayList<ActParticipation>();
        if (ListUtil.isNotEmpty(prtcpList))
        {
            for (ActParticipation actPart : prtcpList)
            {
                if (actPart.getTypecode().equals(ParticipationType.SBJ))
                {
                    act = (Act) actPart.getParticipationAct();
                    continue;
                }
                if (actPart.getTypecode().equals(ParticipationType.DIR))
                {
                    for (int i = 0; i < threeLevelList.size(); i++)
                    {
                        ThreeLevelsPhysicianDTO threeLevel = (ThreeLevelsPhysicianDTO) threeLevelList.get(i);
                        if (threeLevel.getDoctorId().equals(String.valueOf(actPart.getRoleparticipation().getRoleId())))
                        {
                            actPart.setSignatureCode(DataTypeUtil.getCE(threeLevel.getAttendingPhysicianId()));
                            actPart.setFunctionCode(DataTypeUtil.getCE(threeLevel.getChiefDoctorId()));
                            threeLevelList.remove(threeLevel);
                            em.merge(actPart);
                            log.info("ThreeLevelsPhysicianManager-modfiyThreeLevelsPhysician:经治医生不修改");
                        }
                        else
                        {
                            delThreeLevelList.add(actPart);
                            log.info("ThreeLevelsPhysicianManager-modfiyThreeLevelsPhysician:经治医生修改");
                            continue;
                        }
                    }
                }
            }
            // 新增比原来多的关系
            if (ListUtil.isNotEmpty(newThreeLevelList))
            {
                setThreeLevelByAct(act, newThreeLevelList);
            }
            // 删除已经修改的关系
            if (ListUtil.isNotEmpty(delThreeLevelList))
            {
                for (int i = 0; i < delThreeLevelList.size(); i++)
                {
                    em.remove(delThreeLevelList.get(i));
                    em.flush();
                }
            }

        }
    }


    private MedicalTeamDTO convertDtoToRole(Role role) throws Hl7Exception
    {
        MedicalTeamDTO dto = new MedicalTeamDTO();
        dto.setMedicalTeamId(role.getRoleId().toString());
        Organization playerEntities = (Organization) role.getPlayerEntities();
        if (null != playerEntities)
        {
            if (ListUtil.isNotEmpty(playerEntities.getEntyNamesList()))
            {
                for (RimCoreEntyNames names : playerEntities.getEntyNamesList())
                {
                    RimCoreEntyNameUses uses = names.getEntyNameUsesList().get(0);
                    if (uses.getUse().equals(EntityNameUse.L.code().toString()))
                    {
                        dto.setMedicalTeamName(names.getFormatted());
                        break;
                    }
                }
            }
            //医疗组编码
            II ii = playerEntities.getId(EntityIICode.MEDICALTEAMCODE);
            dto.setMedicalCode((ii != null ? ii.extension().toString() : ""));
            //医疗组描述
            ED ed = playerEntities.getDesc();
            dto.setMedicalDesc((ed != null ? ed.stringValue() : ""));
            
        }

        Organization scoperEntities = (Organization) role.getScoperEntities();
        if (null != scoperEntities)
        {
            if (ListUtil.isNotEmpty(scoperEntities.getEntyNamesList()))
            {
                for (RimCoreEntyNames names : scoperEntities.getEntyNamesList())
                {
                    RimCoreEntyNameUses uses = names.getEntyNameUsesList().get(0);
                    if (uses.getUse().equals(EntityNameUse.L.code().toString()))
                    {
                        dto.setWorkgroupName(names.getFormatted());
                        break;
                    }
                }
            }
            dto.setWorkgroupId(role.getScoperEntities().getEntityId().toString());
        }
        // 设置三级医生
        dto.setListThreeLevel(findThreeLevelListByRole(role));

        return dto;
    }


    private List<ThreeLevelsPhysicianDTO> findThreeLevelListByRole(Role role) throws Hl7Exception
    {
        if (null == role) return null;
        List<ActParticipation> list = threeLevelQuery.findThreeLevelListByRole(role);
        List<ThreeLevelsPhysicianDTO> threeLevelList = converThreeLeverDtoToAct(list);
        if (ListUtil.isNotEmpty(threeLevelList))
            return threeLevelList;
        return null;
    }


    private List<ThreeLevelsPhysicianDTO> converThreeLeverDtoToAct(List<ActParticipation> list) throws Hl7Exception
    {

        List<ThreeLevelsPhysicianDTO> threeLeverList = new ArrayList<ThreeLevelsPhysicianDTO>();
        if (ListUtil.isNotEmpty(list))
        {
            for (ActParticipation prtcptns : list)
            {
                if (prtcptns.getTypecode().equals(ParticipationType.DIR))
                {
                    ThreeLevelsPhysicianDTO threeLever = converThreeLevelsPhysicianDTO(prtcptns);
                    threeLeverList.add(threeLever);
                }
            }
        }
        return threeLeverList;
    }


    private ThreeLevelsPhysicianDTO converThreeLevelsPhysicianDTO(ActParticipation prtcptns) throws Hl7Exception
    {
        EmployeeManagerLocal empManager = (EmployeeManagerLocal) Component.getInstance("EmployeeManager");
        ThreeLevelsPhysicianDTO threeLever = new ThreeLevelsPhysicianDTO();
        // 经治医生
        Role role = (Role) prtcptns.getRoleparticipation();
        PatientBaseInfoDTO empInfo = empManager.findPlayEntityByRole(role);
        threeLever.setDoctorId(String.valueOf(role.getRoleId()));
        threeLever.setDoctorName(empInfo.getNatureName());
        // 主治医生
        String attendingPhysicianId = prtcptns.getSignatureCode().code().toString();
        Role attendingPhysicianRole = baseQuery.findRoleById(Long.valueOf(attendingPhysicianId));
        PatientBaseInfoDTO attendingPhysicianInfo = empManager.findPlayEntityByRole(attendingPhysicianRole);
        if (null != attendingPhysicianInfo)
        {
            threeLever.setAttendingPhysicianId(attendingPhysicianId);
            threeLever.setAttendingPhysicianName(attendingPhysicianInfo.getNatureName());
        }

        // 主任医生
        String chiefDoctorId = prtcptns.getFunctionCode().code().toString();
        if (chiefDoctorId.equals("<Null:NI>"))
            chiefDoctorId = "0";
        Role chiefDoctorRole = baseQuery.findRoleById(Long.valueOf(chiefDoctorId));
        PatientBaseInfoDTO chiefDoctorInfo = empManager.findPlayEntityByRole(chiefDoctorRole);
        if (null != chiefDoctorInfo)
        {
            threeLever.setChiefDoctorId(chiefDoctorId);
            threeLever.setChiefDoctorName(chiefDoctorInfo.getNatureName());
        }

        return threeLever;
    }


    
    //创建三级医疗组角色
    private Role converMedicalTeamRole(MedicalTeamDTO dto) throws Hl7Exception
    {
        // 定义三级医生关联对象
        Organization orgWorkgroup = null;
        Organization orgMedicalTeam = null;

        // 根据工作组id拿到工作组RIM实体
        if (StrUtil.isNotEmpty(dto.getWorkgroupId()))
        {
            Role role = baseQuery.findRoleById(Long.valueOf(dto.getWorkgroupId()));
            if (role != null)
                orgWorkgroup = (Organization) role.getPlayerEntities();
        }
        // 根据医疗组编码查看医疗组是否存在
        if (StrUtil.isNotEmpty(dto.getMedicalCode()))
        {
            orgMedicalTeam = departmentQuery.findOrganizationByCode(dto.getMedicalCode());
        }
        if (null == orgMedicalTeam)
        {
            orgMedicalTeam = getEntityFactory().newOrganization(getDataTypeFactory().newCE(EntityCode.MEDICALTEAM.toString()),
                EntityDeterminer.INSTANCE, null);
            converOrganizationTo(orgMedicalTeam, dto);
        }

        // 创建医疗组角色
        Role role = getRoleFactory().newRole(RoleClass.PART, getDataTypeFactory().newCE(RoleCode.MEDICALTEAM.toString()), orgMedicalTeam,
            orgWorkgroup,null);
        
        return role;
    }

}
